package com.hooper.aop;

import cn.hutool.json.JSONUtil;
import com.hooper.anno.PreAuthorize;
import com.hooper.common.JwtHelper;
import com.hooper.exception.BusinessException;
import com.hooper.service.SysMenuService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

import static com.hooper.constant.UserConstant.*;
import static com.hooper.emun.ResultCodeEnum.PERMISSION_NOT_ENOUGH;

/**
 * @author Tim Hooper
 * @version 1.0
 * @time 2023/04/02/20:47
 */
@Aspect
@Slf4j
@Component
public class PermissionCheckAspect {

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Resource
    private SysMenuService menuService;

    @Before("@annotation(preAuthorize)")
    public void check(PreAuthorize preAuthorize) {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        String token = request.getHeader("token");
        //获取用户id
        Long userId = JwtHelper.getUserId(token);
        // 管理员拥有所有权限 不需要校验
        if (Objects.equals(userId, ADMIN_ID)) {
            return;
        }
        String cacheKey = USER_PERMISSIONS + userId;
        String jsonResult = stringRedisTemplate.opsForValue().get(cacheKey);
        //用户可操作的按钮列表
        List<String> btnNameList;
        //缓存中没有，从数据库中查询
        if (StringUtils.isEmpty(jsonResult)) {
            btnNameList = menuService.selectButtonsByUserId(userId);
            stringRedisTemplate.opsForValue().set(cacheKey,
                    JSONUtil.toJsonStr(btnNameList), CACHE_TTL, TimeUnit.MINUTES);
        }
        btnNameList = JSONUtil.toList(jsonResult, String.class);
        log.info("用户-{}可操作的按钮列表：{}", userId, btnNameList);
        // 若请求的权限不在用户可操作的权限列表中，则抛出异常
        if (!btnNameList.contains(preAuthorize.value())) {
            throw new BusinessException(PERMISSION_NOT_ENOUGH);
        }
    }
}
